Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/lxmf_utils.py 356aea3560700c3f630b88b33d4fd46fb6604deb (356aea35) Text, 20.83 KB

T8b949e# SPDX-License-Identifier: 0BSD

Tff7b72import T7ee787base64
Tff7b72import T7ee787json

Tff7b72import T7ee787LXMF

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787telemetry_utils Tff7b72import Te6edf3Telemeter

T8b949e# Columba-compatible app extensions (emoji reactions, reply metadata, etc.)
Te6edf3LXMF_APP_EXTENSIONS_FIELD Tff7b72= T79c0ff16

T8b949e# Raw LXMF integer field identifiers used when classifying "user-facing" payloads
Te6edf3LXMF_FILE_ATTACHMENTS_FIELD Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffFIELD_FILE_ATTACHMENTS
Te6edf3LXMF_IMAGE_FIELD Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffFIELD_IMAGE
Te6edf3LXMF_AUDIO_FIELD Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffFIELD_AUDIO


Tff7b72def Td2a8fflxmf_fields_are_columba_reactionTb4b4b4(Te6edf3lxmf_fieldsTb4b4b4: Tffa657dictTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3lxmf_fieldsTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Te6edf3val Tff7b72= Te6edf3lxmf_fieldsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3LXMF_APP_EXTENSIONS_FIELDTb4b4b4)
Tff7b72return Tffa657isinstanceTb4b4b4(Te6edf3valTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Ta5d6ff"Ta5d6ffreaction_toTa5d6ff" Tff7b72in Te6edf3val


Tff7b72def Td2a8ffis_user_facing_lxmf_payloadTb4b4b4(Te6edf3fieldsTb4b4b4, Te6edf3contentTb4b4b4, Te6edf3titleTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Determine whether an LXMF message represents a user-visible item.

Messages that should NOT raise the notification bell:
- reactions (Columba app_extensions.reaction_to with no other payload)
- telemetry-only messages (FIELD_TELEMETRY / fields["telemetry"] with no body)
- icon-only / appearance-only updates (no body, no attachment)
- empty pings (no content, no title, no attachment)

The helper is intentionally tolerant: ``fields`` may be the rich dict
produced by :func:`convert_lxmf_message_to_dict` (string keys), the raw
LXMF integer-keyed dict, or a JSON-string from the database.
"""
Tff7b72import T7ee787json Tff7b72as T7ee787_json

Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3fields Tff7b72= Te6edf3_jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3fieldsTb4b4b4) Tff7b72if Te6edf3fields Tff7b72else Tb4b4b4{Tb4b4b4}
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149TypeErrorTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3app_ext Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffapp_extensionsTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3app_extTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3raw_app_ext Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3LXMF_APP_EXTENSIONS_FIELDTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3raw_app_extTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3app_ext Tff7b72= Te6edf3raw_app_ext
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3app_extTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Ta5d6ff"Ta5d6ffreaction_toTa5d6ff" Tff7b72in Te6edf3app_extTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ff_has_textTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3value Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657bytesTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3value Tff7b72= Te6edf3valueTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tffa657boolTb4b4b4(Tffa657strTb4b4b4(Te6edf3valueTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72if Te6edf3_has_textTb4b4b4(Te6edf3contentTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72if Te6edf3_has_textTb4b4b4(Te6edf3titleTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True

Te6edf3image Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3imageTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Tb4b4b4(
Te6edf3imageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_sizeTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3imageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72if Te6edf3image Tff7b72is Tff7b72None Tff7b72and Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3LXMF_IMAGE_FIELDTb4b4b4) Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72True

Te6edf3audio Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3audioTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Tb4b4b4(
Te6edf3audioTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudio_sizeTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3audioTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudio_bytesTa5d6ff"Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72if Te6edf3audio Tff7b72is Tff7b72None Tff7b72and Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3LXMF_AUDIO_FIELDTb4b4b4) Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72True

Te6edf3file_attachments Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3file_attachmentsTb4b4b4, Tffa657listTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3file_attachmentsTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72return Tff7b72True
Te6edf3raw_files Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3LXMF_FILE_ATTACHMENTS_FIELDTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3raw_filesTb4b4b4, Tffa657listTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3raw_filesTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72return Tff7b72True

Tff7b72return Tff7b72False


Tff7b72def Td2a8ff_reaction_emoji_from_parsed_lxmf_fieldsTb4b4b4(Te6edf3fieldsTb4b4b4: Tffa657dictTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3app Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffapp_extensionsTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3appTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Ta5d6ff"Ta5d6ffreaction_toTa5d6ff" Tff7b72in Te6edf3appTb4b4b4:
Te6edf3emoji Tff7b72= Tb4b4b4(Te6edf3appTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3emoji Tff7b72or Tff7b72None
Te6edf3raw Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3LXMF_APP_EXTENSIONS_FIELDTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3rawTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Ta5d6ff"Ta5d6ffreaction_toTa5d6ff" Tff7b72in Te6edf3rawTb4b4b4:
Te6edf3emoji Tff7b72= Tb4b4b4(Te6edf3rawTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3emoji Tff7b72or Tff7b72None
Tff7b72return Tff7b72None


Tff7b72def Td2a8fflxmf_sidebar_preview_for_conversation_latest_rowTb4b4b4(
Te6edf3rowTb4b4b4: Tffa657dictTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3local_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3peer_display_nameTb4b4b4: Tffa657strTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Single-line preview for conversation list APIs (reactions have empty body)."""
Te6edf3content Tff7b72= Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3content Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tffa657strTb4b4b4(Te6edf3contentTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tffa657strTb4b4b4(Te6edf3contentTb4b4b4)

Te6edf3fields_raw Tff7b72= Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3fields_rawTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3fields_rawTb4b4b4) Tff7b72if Te6edf3fields_raw Tff7b72else Tb4b4b4{Tb4b4b4}
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3fields_rawTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Te6edf3fields_raw
Tff7b72elseTb4b4b4:
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72except Tb4b4b4(Te6edf3jsonTff7b72.Td2a8ffJSONDecodeErrorTb4b4b4, Tf85149TypeErrorTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3emoji Tff7b72= Te6edf3_reaction_emoji_from_parsed_lxmf_fieldsTb4b4b4(Te6edf3fieldsTb4b4b4)
Tff7b72if Tff7b72not Te6edf3emojiTb4b4b4:
Tff7b72return Tffa657strTb4b4b4(Te6edf3content Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)

Te6edf3is_incoming Tff7b72= Tffa657boolTb4b4b4(Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3is_incomingTb4b4b4:
Te6edf3actor Tff7b72= Te6edf3peer_display_name Tff7b72or Ta5d6ff"Ta5d6ffAnonymous PeerTa5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3src Tff7b72= Tb4b4b4(Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3loc Tff7b72= Tb4b4b4(Te6edf3local_hash Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3actor Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffYouTa5d6ff"
Tff7b72if Te6edf3src Tff7b72and Te6edf3loc Tff7b72and Te6edf3src Tff7b72== Te6edf3loc
Tff7b72else Tb4b4b4(Te6edf3peer_display_name Tff7b72or Ta5d6ff"Ta5d6ffAnonymous PeerTa5d6ff"Tb4b4b4)
Tb4b4b4)

Tff7b72return Ta5d6fffTa5d6ff"Tffd700{Te6edf3actorTffd700}Ta5d6ff reacted Tffd700{Te6edf3emojiTffd700}Ta5d6ff"


Tff7b72def Td2a8ffconvert_lxmf_message_to_dictTb4b4b4(
Te6edf3lxmf_messageTb4b4b4: Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4,
Te6edf3include_attachmentsTb4b4b4: Tffa657bool Tff7b72= Tff7b72TrueTb4b4b4,
Te6edf3reticulumTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e# handle fields
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}
Te6edf3message_fields Tff7b72= Te6edf3lxmf_messageTff7b72.Td2a8ffget_fieldsTb4b4b4(Tb4b4b4)
Te6edf3is_reaction Tff7b72= Tff7b72False
Te6edf3reaction_to Tff7b72= Tff7b72None
Te6edf3reaction_emoji Tff7b72= Tff7b72None
Te6edf3reaction_sender Tff7b72= Tff7b72None
Tff7b72for Te6edf3field_type Tff7b72in Te6edf3message_fieldsTb4b4b4:
Te6edf3value Tff7b72= Te6edf3message_fieldsTb4b4b4[Te6edf3field_typeTb4b4b4]

T8b949e# handle file attachments field
Tff7b72if Te6edf3field_type Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffFIELD_FILE_ATTACHMENTS Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Te6edf3file_attachments Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3file_attachment Tff7b72in Te6edf3valueTb4b4b4:
Tff7b72if Tb4b4b4(
Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3file_attachmentTb4b4b4, Tb4b4b4(Tffa657listTb4b4b4, Tffa657tupleTb4b4b4)Tb4b4b4)
Tff7b72or Tffa657lenTb4b4b4(Te6edf3file_attachmentTb4b4b4) Tff7b72< T79c0ff2
Tb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3file_name Tff7b72= Te6edf3file_attachmentTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3file_data Tff7b72= Te6edf3file_attachmentTb4b4b4[T79c0ff1Tb4b4b4]
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3file_dataTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3file_bytes Tff7b72= Tff7b72None
Tff7b72if Te6edf3include_attachmentsTb4b4b4:
Te6edf3file_bytes Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3file_dataTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(
Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3file_attachmentsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fffile_nameTa5d6ff"Tb4b4b4: Tffa657strTb4b4b4(Te6edf3file_nameTb4b4b4) Tff7b72if Te6edf3file_name Tff7b72else Ta5d6ff"Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fffile_sizeTa5d6ff"Tb4b4b4: Tffa657lenTb4b4b4(Te6edf3file_dataTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fffile_bytesTa5d6ff"Tb4b4b4: Te6edf3file_bytesTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3file_attachments

T8b949e# handle image field
Tff7b72if Tb4b4b4(
Te6edf3field_type Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffFIELD_IMAGE
Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tb4b4b4(Tffa657listTb4b4b4, Tffa657tupleTb4b4b4)Tb4b4b4)
Tff7b72and Tffa657lenTb4b4b4(Te6edf3valueTb4b4b4) Tff7b72>Tff7b72= T79c0ff2
Tb4b4b4)Tb4b4b4:
Te6edf3image_type Tff7b72= Te6edf3valueTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3image_data Tff7b72= Te6edf3valueTb4b4b4[T79c0ff1Tb4b4b4]
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3image_dataTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3image_bytes Tff7b72= Tff7b72None
Tff7b72if Te6edf3include_attachmentsTb4b4b4:
Te6edf3image_bytes Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3image_dataTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)

Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4: Te6edf3image_typeTb4b4b4,
Ta5d6ff"Ta5d6ffimage_sizeTa5d6ff"Tb4b4b4: Tffa657lenTb4b4b4(Te6edf3image_dataTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4: Te6edf3image_bytesTb4b4b4,
Tb4b4b4}

T8b949e# handle audio field
Tff7b72if Tb4b4b4(
Te6edf3field_type Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffFIELD_AUDIO
Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tb4b4b4(Tffa657listTb4b4b4, Tffa657tupleTb4b4b4)Tb4b4b4)
Tff7b72and Tffa657lenTb4b4b4(Te6edf3valueTb4b4b4) Tff7b72>Tff7b72= T79c0ff2
Tb4b4b4)Tb4b4b4:
Te6edf3audio_mode Tff7b72= Te6edf3valueTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3audio_data Tff7b72= Te6edf3valueTb4b4b4[T79c0ff1Tb4b4b4]
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3audio_dataTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3audio_bytes Tff7b72= Tff7b72None
Tff7b72if Te6edf3include_attachmentsTb4b4b4:
Te6edf3audio_bytes Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3audio_dataTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)

Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffaudio_modeTa5d6ff"Tb4b4b4: Te6edf3audio_modeTb4b4b4,
Ta5d6ff"Ta5d6ffaudio_sizeTa5d6ff"Tb4b4b4: Tffa657lenTb4b4b4(Te6edf3audio_dataTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffaudio_bytesTa5d6ff"Tb4b4b4: Te6edf3audio_bytesTb4b4b4,
Tb4b4b4}

T8b949e# handle telemetry field
Tff7b72if Te6edf3field_type Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffFIELD_TELEMETRYTb4b4b4:
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fftelemetryTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3TelemeterTff7b72.Td2a8fffrom_packedTb4b4b4(Te6edf3valueTb4b4b4)

T8b949e# handle commands field
Tff7b72if Te6edf3field_type Tff7b72in Tb4b4b4(Te6edf3LXMFTff7b72.Td2a8ffFIELD_COMMANDSTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4:
Te6edf3processed_commands Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3cmd Tff7b72in Te6edf3valueTb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3cmdTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3new_cmd Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72for Te6edf3kTb4b4b4, Te6edf3v Tff7b72in Te6edf3cmdTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3kTb4b4b4, Tffa657intTb4b4b4)Tb4b4b4:
Te6edf3new_cmdTb4b4b4[Ta5d6fffTa5d6ff"Ta5d6ff0xTffd700{Te6edf3kTffd700:Ta5d6ff02xTffd700}Ta5d6ff"Tb4b4b4] Tff7b72= Te6edf3v
Tff7b72elseTb4b4b4:
Te6edf3new_cmdTb4b4b4[Tffa657strTb4b4b4(Te6edf3kTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3v
Te6edf3processed_commandsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3new_cmdTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3processed_commandsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3cmdTb4b4b4)
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3new_cmd Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72for Te6edf3kTb4b4b4, Te6edf3v Tff7b72in Te6edf3valueTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3kTb4b4b4, Tffa657intTb4b4b4)Tb4b4b4:
Te6edf3new_cmdTb4b4b4[Ta5d6fffTa5d6ff"Ta5d6ff0xTffd700{Te6edf3kTffd700:Ta5d6ff02xTffd700}Ta5d6ff"Tb4b4b4] Tff7b72= Te6edf3v
Tff7b72elseTb4b4b4:
Te6edf3new_cmdTb4b4b4[Tffa657strTb4b4b4(Te6edf3kTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3v
Te6edf3processed_commandsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3new_cmdTb4b4b4)
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffcommandsTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3processed_commands

T8b949e# handle reply_to field
Tff7b72if Te6edf3field_type Tff7b72== T79c0ff0x30Tb4b4b4:
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffreply_toTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3valueTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657bytesTb4b4b4) Tff7b72else Te6edf3value
Tff7b72if Te6edf3field_type Tff7b72== T79c0ff0x31Tb4b4b4:
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffreply_quoted_contentTa5d6ff"Tb4b4b4] Tff7b72= Tb4b4b4(
Te6edf3valueTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657bytesTb4b4b4)
Tff7b72else Te6edf3value
Tb4b4b4)

Tff7b72if Te6edf3field_type Tff7b72== Te6edf3LXMF_APP_EXTENSIONS_FIELD Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffapp_extensionsTa5d6ff"Tb4b4b4] Tff7b72= Tffa657dictTb4b4b4(Te6edf3valueTb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ffreaction_toTa5d6ff" Tff7b72in Te6edf3valueTb4b4b4:
Te6edf3is_reaction Tff7b72= Tff7b72True
Te6edf3reaction_to Tff7b72= Te6edf3valueTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreaction_toTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"
Te6edf3reaction_emoji Tff7b72= Te6edf3valueTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"
Te6edf3reaction_sender Tff7b72= Te6edf3valueTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsenderTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"

T8b949e# convert 0.0-1.0 progress to 0.00-100 percentage
Te6edf3progress_percentage Tff7b72= Tffa657roundTb4b4b4(Te6edf3lxmf_messageTff7b72.Td2a8ffprogress Tff7b72* T79c0ff100Tb4b4b4, T79c0ff2Tb4b4b4)

T8b949e# get rssi
Te6edf3rssi Tff7b72= Te6edf3lxmf_messageTff7b72.Td2a8ffrssi
Tff7b72if Te6edf3rssi Tff7b72is Tff7b72None Tff7b72and Te6edf3reticulumTb4b4b4:
Te6edf3rssi Tff7b72= Te6edf3reticulumTff7b72.Td2a8ffget_packet_rssiTb4b4b4(Te6edf3lxmf_messageTff7b72.Td2a8ffhashTb4b4b4)

T8b949e# get snr
Te6edf3snr Tff7b72= Te6edf3lxmf_messageTff7b72.Td2a8ffsnr
Tff7b72if Te6edf3snr Tff7b72is Tff7b72None Tff7b72and Te6edf3reticulumTb4b4b4:
Te6edf3snr Tff7b72= Te6edf3reticulumTff7b72.Td2a8ffget_packet_snrTb4b4b4(Te6edf3lxmf_messageTff7b72.Td2a8ffhashTb4b4b4)

T8b949e# get quality
Te6edf3quality Tff7b72= Te6edf3lxmf_messageTff7b72.Td2a8ffq
Tff7b72if Te6edf3quality Tff7b72is Tff7b72None Tff7b72and Te6edf3reticulumTb4b4b4:
Te6edf3quality Tff7b72= Te6edf3reticulumTff7b72.Td2a8ffget_packet_qTb4b4b4(Te6edf3lxmf_messageTff7b72.Td2a8ffhashTb4b4b4)

T8b949e# get reply_to_hash from fields if present
Te6edf3reply_to_hash Tff7b72= Tff7b72None
Tff7b72if T79c0ff0x30 Tff7b72in Te6edf3message_fieldsTb4b4b4:
Te6edf3val Tff7b72= Te6edf3message_fieldsTb4b4b4[T79c0ff0x30Tb4b4b4]
Te6edf3reply_to_hash Tff7b72= Te6edf3valTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valTb4b4b4, Tffa657bytesTb4b4b4) Tff7b72else Te6edf3val

Te6edf3content Tff7b72= Tb4b4b4(
Te6edf3lxmf_messageTff7b72.Td2a8ffcontentTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3lxmf_messageTff7b72.Td2a8ffcontent
Tff7b72else Ta5d6ff"Ta5d6ff"
Tb4b4b4)

T8b949e# auto-detect reply from content if not present
Tff7b72if Tff7b72not Te6edf3reply_to_hash Tff7b72and Te6edf3content Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3contentTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72import T7ee787re

Te6edf3match Tff7b72= Te6edf3reTff7b72.Td2a8ffsearchTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ff^> ([a-fA-F0-9]Tffd700{32}Ta5d6ff)Ta5d6ff\Ta5d6ffs*Ta5d6ff\Ta5d6ffn?Ta5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4)
Tff7b72if Te6edf3matchTb4b4b4:
Te6edf3reply_to_hash Tff7b72= Te6edf3matchTff7b72.Td2a8ffgroupTb4b4b4(T79c0ff1Tb4b4b4)

Te6edf3out Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8ffsource_hashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8ffdestination_hashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8ffincomingTb4b4b4,
Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4: Te6edf3convert_lxmf_state_to_stringTb4b4b4(Te6edf3lxmf_messageTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4: Te6edf3progress_percentageTb4b4b4,
Ta5d6ff"Ta5d6ffmethodTa5d6ff"Tb4b4b4: Te6edf3convert_lxmf_method_to_stringTb4b4b4(Te6edf3lxmf_messageTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffdelivery_attemptsTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8ffdelivery_attemptsTb4b4b4,
Ta5d6ff"Ta5d6ffnext_delivery_attempt_atTa5d6ff"Tb4b4b4: Tffa657getattrTb4b4b4(
Te6edf3lxmf_messageTb4b4b4,
Ta5d6ff"Ta5d6ffnext_delivery_attemptTa5d6ff"Tb4b4b4,
Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4, T8b949e# attribute may not exist yet
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8fftitleTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3lxmf_messageTff7b72.Td2a8fftitle
Tff7b72else Ta5d6ff"Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Te6edf3contentTb4b4b4,
Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4: Te6edf3fieldsTb4b4b4,
Ta5d6ff"Ta5d6fftimestampTa5d6ff"Tb4b4b4: Te6edf3lxmf_messageTff7b72.Td2a8fftimestampTb4b4b4,
Ta5d6ff"Ta5d6ffrssiTa5d6ff"Tb4b4b4: Te6edf3rssiTb4b4b4,
Ta5d6ff"Ta5d6ffsnrTa5d6ff"Tb4b4b4: Te6edf3snrTb4b4b4,
Ta5d6ff"Ta5d6ffqualityTa5d6ff"Tb4b4b4: Te6edf3qualityTb4b4b4,
Ta5d6ff"Ta5d6ffreply_to_hashTa5d6ff"Tb4b4b4: Te6edf3reply_to_hashTb4b4b4,
Ta5d6ff"Ta5d6ffis_reactionTa5d6ff"Tb4b4b4: Te6edf3is_reactionTb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3is_reactionTb4b4b4:
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffreaction_toTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3reaction_to
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffreaction_emojiTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3reaction_emoji
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffreaction_senderTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3reaction_sender
Tff7b72return Te6edf3out


Tff7b72def Td2a8ffconvert_lxmf_state_to_stringTb4b4b4(Te6edf3lxmf_messageTb4b4b4: Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4)Tb4b4b4:
T8b949e# convert state to string
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffunknownTa5d6ff"
Tff7b72if Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffGENERATINGTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffgeneratingTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffOUTBOUNDTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffoutboundTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffSENDINGTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffsendingTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffSENTTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffsentTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffDELIVEREDTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffdeliveredTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffREJECTEDTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffrejectedTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffCANCELLEDTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6ffcancelledTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILEDTb4b4b4:
Te6edf3lxmf_message_state Tff7b72= Ta5d6ff"Ta5d6fffailedTa5d6ff"

Tff7b72return Te6edf3lxmf_message_state


Tff7b72def Td2a8ffconvert_lxmf_method_to_stringTb4b4b4(Te6edf3lxmf_messageTb4b4b4: Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4)Tb4b4b4:
T8b949e# convert method to string
Te6edf3lxmf_message_method Tff7b72= Ta5d6ff"Ta5d6ffunknownTa5d6ff"
Tff7b72if Te6edf3lxmf_messageTff7b72.Td2a8ffmethod Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffOPPORTUNISTICTb4b4b4:
Te6edf3lxmf_message_method Tff7b72= Ta5d6ff"Ta5d6ffopportunisticTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffmethod Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffDIRECTTb4b4b4:
Te6edf3lxmf_message_method Tff7b72= Ta5d6ff"Ta5d6ffdirectTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffmethod Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffPROPAGATEDTb4b4b4:
Te6edf3lxmf_message_method Tff7b72= Ta5d6ff"Ta5d6ffpropagatedTa5d6ff"
Tff7b72elif Te6edf3lxmf_messageTff7b72.Td2a8ffmethod Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffPAPERTb4b4b4:
Te6edf3lxmf_message_method Tff7b72= Ta5d6ff"Ta5d6ffpaperTa5d6ff"

Tff7b72return Te6edf3lxmf_message_method


Tff7b72def Td2a8ffconvert_db_lxmf_message_to_dictTb4b4b4(
Te6edf3db_lxmf_messageTb4b4b4,
Te6edf3include_attachmentsTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3fields_str Tff7b72= Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4, Ta5d6ff"Tffd700{}Ta5d6ff"Tb4b4b4)
Te6edf3fields Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3fields_strTb4b4b4) Tff7b72if Te6edf3fields_str Tff7b72else Tb4b4b4{Tb4b4b4}
Tff7b72except Tb4b4b4(Te6edf3jsonTff7b72.Td2a8ffJSONDecodeErrorTb4b4b4, Tf85149TypeErrorTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}

Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3is_reaction Tff7b72= Tff7b72False
Te6edf3reaction_to Tff7b72= Tff7b72None
Te6edf3reaction_emoji Tff7b72= Tff7b72None
Te6edf3reaction_sender Tff7b72= Tff7b72None
Te6edf3app Tff7b72= Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffapp_extensionsTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3appTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Ta5d6ff"Ta5d6ffreaction_toTa5d6ff" Tff7b72in Te6edf3appTb4b4b4:
Te6edf3is_reaction Tff7b72= Tff7b72True
Te6edf3reaction_to Tff7b72= Te6edf3appTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreaction_toTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"
Te6edf3reaction_emoji Tff7b72= Te6edf3appTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"
Te6edf3reaction_sender Tff7b72= Te6edf3appTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsenderTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"

T8b949e# normalize commands if present
Tff7b72if Ta5d6ff"Ta5d6ffcommandsTa5d6ff" Tff7b72in Te6edf3fieldsTb4b4b4:
Te6edf3cmds Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffcommandsTa5d6ff"Tb4b4b4]
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3cmdsTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Te6edf3new_cmds Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3cmd Tff7b72in Te6edf3cmdsTb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3cmdTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3new_cmd Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72for Te6edf3kTb4b4b4, Te6edf3v Tff7b72in Te6edf3cmdTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
T8b949e# normalize key to 0xXX format if it's a number string
Tff7b72tryTb4b4b4:
Te6edf3ki Tff7b72= Tff7b72None
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3kTb4b4b4, Tffa657intTb4b4b4)Tb4b4b4:
Te6edf3ki Tff7b72= Te6edf3k
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3kTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3kTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ff0xTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3ki Tff7b72= Tffa657intTb4b4b4(Te6edf3kTb4b4b4, T79c0ff16Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3ki Tff7b72= Tffa657intTb4b4b4(Te6edf3kTb4b4b4)

Tff7b72if Te6edf3ki Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3new_cmdTb4b4b4[Ta5d6fffTa5d6ff"Ta5d6ff0xTffd700{Te6edf3kiTffd700:Ta5d6ff02xTffd700}Ta5d6ff"Tb4b4b4] Tff7b72= Te6edf3v
Tff7b72elseTb4b4b4:
Te6edf3new_cmdTb4b4b4[Tffa657strTb4b4b4(Te6edf3kTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3v
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149TypeErrorTb4b4b4)Tb4b4b4:
Te6edf3new_cmdTb4b4b4[Tffa657strTb4b4b4(Te6edf3kTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3v
Te6edf3new_cmdsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3new_cmdTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3new_cmdsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3cmdTb4b4b4)
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffcommandsTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3new_cmds

T8b949e# strip attachments if requested
Tff7b72if Tff7b72not Te6edf3include_attachmentsTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ffimageTa5d6ff" Tff7b72in Te6edf3fieldsTb4b4b4:
T8b949e# keep type but strip bytes
Te6edf3image_size Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_sizeTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0
Te6edf3b64_bytes Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3image_size Tff7b72and Te6edf3b64_bytesTb4b4b4:
T8b949e# Optimized size calculation without full decoding
Te6edf3image_size Tff7b72= Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3b64_bytesTb4b4b4) Tff7b72* T79c0ff3Tb4b4b4) Tff7b72/Tff7b72/ T79c0ff4
Tff7b72if Te6edf3b64_bytesTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff==Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3image_size Tff7b72-Tff7b72= T79c0ff2
Tff7b72elif Te6edf3b64_bytesTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3image_size Tff7b72-Tff7b72= T79c0ff1
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4: Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_sizeTa5d6ff"Tb4b4b4: Te6edf3image_sizeTb4b4b4,
Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Tb4b4b4}
Tff7b72if Ta5d6ff"Ta5d6ffaudioTa5d6ff" Tff7b72in Te6edf3fieldsTb4b4b4:
T8b949e# keep mode but strip bytes
Te6edf3audio_size Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudio_sizeTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0
Te6edf3b64_bytes Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudio_bytesTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3audio_size Tff7b72and Te6edf3b64_bytesTb4b4b4:
Te6edf3audio_size Tff7b72= Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3b64_bytesTb4b4b4) Tff7b72* T79c0ff3Tb4b4b4) Tff7b72/Tff7b72/ T79c0ff4
Tff7b72if Te6edf3b64_bytesTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff==Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3audio_size Tff7b72-Tff7b72= T79c0ff2
Tff7b72elif Te6edf3b64_bytesTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3audio_size Tff7b72-Tff7b72= T79c0ff1
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffaudio_modeTa5d6ff"Tb4b4b4: Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudio_modeTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffaudio_sizeTa5d6ff"Tb4b4b4: Te6edf3audio_sizeTb4b4b4,
Ta5d6ff"Ta5d6ffaudio_bytesTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Tb4b4b4}
Tff7b72if Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff" Tff7b72in Te6edf3fieldsTb4b4b4:
T8b949e# keep file names but strip bytes
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Tffa657lenTb4b4b4(Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3file_size Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4]Tb4b4b4[Te6edf3iTb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffile_sizeTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0
Te6edf3b64_bytes Tff7b72= Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4]Tb4b4b4[Te6edf3iTb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffile_bytesTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3file_size Tff7b72and Te6edf3b64_bytesTb4b4b4:
Te6edf3file_size Tff7b72= Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3b64_bytesTb4b4b4) Tff7b72* T79c0ff3Tb4b4b4) Tff7b72/Tff7b72/ T79c0ff4
Tff7b72if Te6edf3b64_bytesTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff==Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3file_size Tff7b72-Tff7b72= T79c0ff2
Tff7b72elif Te6edf3b64_bytesTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3file_size Tff7b72-Tff7b72= T79c0ff1
Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4]Tb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6fffile_nameTa5d6ff"Tb4b4b4: Te6edf3fieldsTb4b4b4[Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4]Tb4b4b4[Te6edf3iTb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffile_nameTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fffile_sizeTa5d6ff"Tb4b4b4: Te6edf3file_sizeTb4b4b4,
Ta5d6ff"Ta5d6fffile_bytesTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Tb4b4b4}

T8b949e# ensure created_at and updated_at have Z suffix for UTC if they don't have a timezone
Te6edf3created_at Tff7b72= Tffa657strTb4b4b4(Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72if Te6edf3created_at Tff7b72and Ta5d6ff"Ta5d6ff+Ta5d6ff" Tff7b72not Tff7b72in Te6edf3created_at Tff7b72and Ta5d6ff"Ta5d6ffZTa5d6ff" Tff7b72not Tff7b72in Te6edf3created_atTb4b4b4:
Te6edf3created_at Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ffZTa5d6ff"

Te6edf3updated_at Tff7b72= Tffa657strTb4b4b4(Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72if Te6edf3updated_at Tff7b72and Ta5d6ff"Ta5d6ff+Ta5d6ff" Tff7b72not Tff7b72in Te6edf3updated_at Tff7b72and Ta5d6ff"Ta5d6ffZTa5d6ff" Tff7b72not Tff7b72in Te6edf3updated_atTb4b4b4:
Te6edf3updated_at Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ffZTa5d6ff"

Te6edf3out Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4: Tffa657boolTb4b4b4(Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffmethodTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmethodTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffunknownTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdelivery_attemptsTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffdelivery_attemptsTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffnext_delivery_attempt_atTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffnext_delivery_attempt_atTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4: Te6edf3fieldsTb4b4b4,
Ta5d6ff"Ta5d6fftimestampTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6fftimestampTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffrssiTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffrssiTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffsnrTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffsnrTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffqualityTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffqualityTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffis_spamTa5d6ff"Tb4b4b4: Tffa657boolTb4b4b4(Te6edf3db_lxmf_messageTb4b4b4[Ta5d6ff"Ta5d6ffis_spamTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffreply_to_hashTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreply_to_hashTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffattachments_strippedTa5d6ff"Tb4b4b4: Tffa657boolTb4b4b4(Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffattachments_strippedTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpath_hops_at_sendTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpath_hops_at_sendTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpath_interface_at_sendTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpath_interface_at_sendTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpath_finding_measureTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpath_finding_measureTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpath_row_hash_hexTa5d6ff"Tb4b4b4: Te6edf3db_lxmf_messageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpath_row_hash_hexTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4: Te6edf3created_atTb4b4b4,
Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4: Te6edf3updated_atTb4b4b4,
Ta5d6ff"Ta5d6ffis_reactionTa5d6ff"Tb4b4b4: Te6edf3is_reactionTb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3is_reactionTb4b4b4:
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffreaction_toTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3reaction_to
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffreaction_emojiTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3reaction_emoji
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffreaction_senderTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3reaction_sender
Tff7b72return Te6edf3out


Tff7b72def Td2a8ffcompute_lxmf_conversation_unread_from_latest_rowTb4b4b4(Te6edf3rowTb4b4b4, Tff7b72*Tb4b4b4, Te6edf3require_user_facingTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e"""Return whether the conversation row should appear as unread.

Uses ``lxmf_conversation_read_state.last_read_at`` only. The latest message
must be incoming; outbound-only threads are not unread (matches
``filter_unread`` in ``MessageHandler.get_conversations``).

When ``require_user_facing`` is True, the row's latest message must also be
user-facing (i.e. not a bare reaction / telemetry / icon-only payload).
Used by the notification bell so silent system messages do not raise the
unread badge.
"""
Tff7b72from T7ee787datetime Tff7b72import Te6edf3UTCTb4b4b4, Te6edf3datetime

Tff7b72if Tff7b72not Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72if Te6edf3require_user_facing Tff7b72and Tff7b72not Te6edf3is_user_facing_lxmf_payloadTb4b4b4(
Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Te6edf3last_read_at_raw Tff7b72= Te6edf3rowTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_read_atTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3last_read_at_rawTb4b4b4:
Tff7b72return Tff7b72True
Te6edf3last_read_at Tff7b72= Te6edf3datetimeTff7b72.Td2a8fffromisoformatTb4b4b4(Te6edf3last_read_at_rawTb4b4b4)
Tff7b72if Te6edf3last_read_atTff7b72.Td2a8fftzinfo Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3last_read_at Tff7b72= Te6edf3last_read_atTff7b72.Td2a8ffreplaceTb4b4b4(Te6edf3tzinfoTff7b72=Te6edf3UTCTb4b4b4)
Tff7b72return Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6fftimestampTa5d6ff"Tb4b4b4] Tff7b72> Te6edf3last_read_atTff7b72.Td2a8fftimestampTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────